<?php


namespace App\Utils;


use Hyperf\Redis\RedisFactory;

/**
 * redis锁
 * Class Lock
 * @package App\Utils
 */
class Lock
{
    private $redis;

    public function __construct()
    {
        $this->redis = di(RedisFactory::class)->get('default');
    }

    /**
     * 加锁
     * @param string $key
     * @param int $ttl
     * @return bool
     */
    public function lock($key = '', $ttl = 2)
    {
        if ($key != '' && is_numeric($ttl) && $ttl > 0 && floor($ttl) == $ttl) {
            return $this->redis->set($key, '1', ['NX', 'EX' => $ttl]);
        } else {
            return false;
        }
    }

    /**
     * 解锁
     * @param string $key
     */
    public function unlock($key = '')
    {
        if ($key != '') {
            $this->redis->del($key);
        }
    }


    /**
     * 多个key加锁
     * @param array $keys
     * @param int $ttl
     * $keys = [
     *      $key,$key2
     * ]
     *
     * @return array|bool
     * array = [
     *      $key,$key2
     * ]
     */
    public function locks(array $keys, int $ttl = 2)
    {
        $lockKeys = [];
        $lockFail = false;
        foreach ($keys as $key) {
            $state = $this->lock($key, $ttl);
            if ($state) {
                array_push($lockKeys, $key);
            } else {
                $lockFail = true;
                break;
            }
        }

        if ($lockFail) {
            $this->unlocks($lockKeys);
            return false;
        }
        return $lockKeys;
    }

    /**
     * 解锁多个key
     * @param array $lockKeys
     */
    public function unlocks(array $lockKeys)
    {
        foreach ($lockKeys as $key) {
            $this->unlock($key);
        }
    }
}